/*
 * @Descripttion :
 * @version      :
 * @Author       : Kevincoooool
 * @Date         : 2021-09-04 16:11:59
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2022-12-29 19:58:36
 * @FilePath: \3.lvgl_v9\main\main.c
 */
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_timer.h"
#include "ui.h"
#include "DHT11.h"
#include "lv_demos.h"
#include "lvgl_helpers.h"
#include "esp_freertos_hooks.h"

#include "RGB.h"
#include "init.h"

#include "driver/gpio.h"

#define GPIO_OUTPUT_IO_0    GPIO_NUM_1

//-------------任务句柄----------------//
TaskHandle_t dhtTask;
//-------------定时器句柄定义和回调函数-----------//
esp_timer_handle_t TempHumi_timer = 0;

void DHT11_task(void *arg);

static void gui_task(void *arg);

static void pwm(void *arg);

void dht11_timer_init();

//定时器的回调函数
void timer_periodic(void *arg);

void app_main(void)
{   

   rgb_init();
   dht11_timer_init();
   temp_init();


   //任务创建
   //创建任务，并且使用一个核心，毕竟ESP32是双核，0是第一个核心，1是第二个。
   //任务栈的大小由自己来测试，代码这里有空余多的空间。
   //任务级别尽量高点，这里为2；再放入任务句柄，以便用于定时中断来恢复任务
   xTaskCreatePinnedToCore(DHT11_task, "dht11_task", 1024 * 2, NULL, 2, &dhtTask, 1);
   xTaskCreatePinnedToCore(RGB_test, "RGB_test", 1024 * 3, NULL, 4, NULL, 1);
   xTaskCreatePinnedToCore(gui_task, "gui task", 1024 * 4, NULL, 1, NULL, 0);
   //xTaskCreate(pwm, "pwm task", 1024*2, NULL, 1, NULL);
}
void dht11_timer_init()
{
   //-----------配置定时器-------------//
    const esp_timer_create_args_t start_dht = {
        .callback = &timer_periodic,
        .arg = NULL,
        .name = "PeriodicTimer"};

    //----------定时器初始化-----------//
    esp_timer_init();
    esp_timer_create(&start_dht, &TempHumi_timer);//创建定时器
    esp_timer_start_periodic(TempHumi_timer, 1 * 1000 * 1000);//定时器每x*100万微秒（x秒）中断一次
}

void DHT11_task(void *arg)
{
   DHT11_init(GPIO_NUM_1);
   while(1) {
      tem_hum=DHT11_read();
      printf("Temperature is %d \n", tem_hum.temperature);
      printf("Humidity is %d\n", tem_hum.humidity);
      printf("Status code is %d\n", tem_hum.status);
      //tem_hum_update(tem_hum.temperature,tem_hum.humidity);
      //add_data(tem_hum.temperature,tem_hum.humidity);
      //add_data_to_more(tem_hum.temperature,0);
      add_data_to_more(get_temp_sensor(),0);

      vTaskSuspend(NULL);//这里是把自己挂起，挂起后该任务被暂停，不恢复是不运行的
   }
}

//定时器的回调函数
void timer_periodic(void *arg)
{
    vTaskResume(dhtTask); //恢复任务
}
static void pwm(void *arg)
{
    int i=0;
    while(1){
        printf("r=%d,g=%d,b=%d \n", i%3==0?0:1, i%3==1?0:1,i%3==2?0:1);
        //1为高电平，0为低电平
        gpio_set_level(GPIO_NUM_40,i%3==0?0:1);   // 红
        gpio_set_level(GPIO_NUM_41,i%3==1?0:1);   // 绿
        gpio_set_level(GPIO_NUM_42,i%3==2?0:1);   // 蓝

        vTaskDelay(200 / portTICK_PERIOD_MS);
        i++;
        if(i>2)i=0;
    }
}

static void lv_tick_task(void *arg)
{
   (void)arg;
   lv_tick_inc(10);
}
SemaphoreHandle_t xGuiSemaphore;

static void gui_task(void *arg)
{
   xGuiSemaphore = xSemaphoreCreateMutex();
   lv_init();          //lvgl内核初始化
   lvgl_driver_init(); //lvgl显示接口初始化

   /* Example for 1) */
   static lv_disp_draw_buf_t draw_buf;

   lv_color_t *buf1 = heap_caps_malloc(DISP_BUF_SIZE * 2, MALLOC_CAP_DMA);
   lv_color_t *buf2 = heap_caps_malloc(DISP_BUF_SIZE * 2, MALLOC_CAP_DMA);

   // lv_color_t *buf1 = (lv_color_t *)heap_caps_malloc(DISP_BUF_SIZE * 2, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
	// lv_color_t *buf2 = (lv_color_t *)heap_caps_malloc(DISP_BUF_SIZE * 2, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);


   lv_disp_draw_buf_init(&draw_buf, buf1, buf2, DLV_HOR_RES_MAX * DLV_VER_RES_MAX); /*Initialize the display buffer*/

   static lv_disp_drv_t disp_drv;         /*A variable to hold the drivers. Must be static or global.*/
   lv_disp_drv_init(&disp_drv);           /*Basic initialization*/
   disp_drv.draw_buf = &draw_buf;         /*Set an initialized buffer*/
   disp_drv.flush_cb = disp_driver_flush; /*Set a flush callback to draw to the display*/
   disp_drv.hor_res = 320;                /*Set the horizontal resolution in pixels*/
   disp_drv.ver_res = 240;                /*Set the vertical resolution in pixels*/
   lv_disp_drv_register(&disp_drv);       /*Register the driver and save the created display objects*/
   /*触摸屏输入接口配置*/
	lv_indev_drv_t indev_drv;
	lv_indev_drv_init(&indev_drv);
	indev_drv.read_cb = touch_driver_read;
	indev_drv.type = LV_INDEV_TYPE_POINTER;
	lv_indev_drv_register(&indev_drv);

   // esp_register_freertos_tick_hook(lv_tick_task);

	/* 创建一个定时器中断来进入 lv_tick_inc 给lvgl运行提供心跳 这里是10ms一次 主要是动画运行要用到 */
	const esp_timer_create_args_t periodic_timer_args = {
		.callback = &lv_tick_task,
		.name = "periodic_gui"};
	esp_timer_handle_t periodic_timer;
	ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
	ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, 10 * 1000));

   //lv_example_event_2();
   //lv_ex_chart_1();
   //show_temp_hum();
   show_temp_hum_more();
   while (1)
   {
      /* Delay 1 tick (assumes FreeRTOS tick is 10ms */
      vTaskDelay(pdMS_TO_TICKS(10));

      /* Try to take the semaphore, call lvgl related function on success */
      if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY))
      {
         lv_timer_handler();
         xSemaphoreGive(xGuiSemaphore);
      }
   }
}